package org.desktop.web.server;

import java.io.InputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.text.StrSubstitutor;
import org.desktop.web.client.user.UserService;
import org.desktop.web.server.locator.ServiceLocator;
import org.desktop.web.server.locator.ServiceLocator.ServiceName;
import org.desktop.web.server.util.RpcUtil;
import org.desktop.web.shared.Response;
import org.desktop.web.shared.domain.entities.Email;
import org.desktop.web.shared.domain.entities.SubProject;
import org.desktop.web.shared.domain.entities.User;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.sencha.gxt.data.shared.loader.PagingLoadConfig;
import com.sencha.gxt.data.shared.loader.PagingLoadResult;

public class UserServiceImpl extends AbstractPagingService<User> implements
		UserService {

	String userses = RpcUtil.createUrlService(ServiceLocator.find(ServiceName.TIMESHEET_SERVICE),"userses");
	String usersprojects = RpcUtil.createUrlService(ServiceLocator.find(ServiceName.TIMESHEET_SERVICE),"usersprojects");

	String updateUser = RpcUtil.createUrlService(ServiceLocator.find(ServiceName.TIMESHEET_SERVICE),"userses/${id}");
	private String emailsUpdate = RpcUtil.createUrlService(ServiceLocator.find(ServiceName.TIMESHEET_SERVICE),"emailses/${idEmail}");
	private String emails = RpcUtil.createUrlService(ServiceLocator.find(ServiceName.TIMESHEET_SERVICE),"emailses");

	@Override
	public boolean hasSubProjects(List<SubProject> subprojects)
			throws Exception {
		// TODO Auto-generated method stub
		boolean result = false;
		for (Iterator iterator = subprojects.iterator(); iterator.hasNext();) {
			SubProject subProject = (SubProject) iterator.next();
			int id = subProject.getId();
			HttpURLConnection con = RpcUtil.getUrlConnection(new URL(
					usersprojects + "/subproject/" + id), "GET");
			RpcUtil.setToken(con, getThreadLocalRequest());
			InputStream in = con.getInputStream();
			int code = con.getResponseCode();
			in.close();
			result = code == 302;
			if (result) {
				break;
			}
		}
		return result;
	}

	@Override
	public boolean update(final String token, Serializable user) {
		int code = 500;
		try {
			User u = (User) user;
			Map<String, String> valueMap = new HashMap<String, String>();
			valueMap.put("id", Integer.toString(u.getId()));
			StrSubstitutor subs = new StrSubstitutor(valueMap);
			HttpURLConnection con = RpcUtil.getUrlConnection(
					new URL(subs.replace(updateUser)), "PUT");
			con.setRequestProperty("Accept", "application/json");
			con.setRequestProperty("token", token);
			ObjectMapper objmapper = new ObjectMapper();
			String json = objmapper.writeValueAsString(u);
			OutputStream out = con.getOutputStream();
			System.out.println("UserService.update() " + json);
			out.write(json.getBytes());
			out.flush();
			out.close();
			InputStream in = con.getInputStream();
			code = con.getResponseCode();
			in.close();
			if (code == 200) {
				List<Email> emails = ((User) user).getEmails();
				for (final Email em : emails) {
					System.out.println(em.getIdEmail());
					String _url = "";
					String method = "";
					em.setIdUsers(u);
					if (em.getIdEmail() != null) {
						StrSubstitutor strSubs = new StrSubstitutor(
								new HashMap<String, String>() {
									{
										put("idEmail", Integer.toString(em
												.getIdEmail()));
									}
								});
						_url = strSubs.replace(emailsUpdate);
						method = "PUT";
					} else {
						_url = this.emails;
						method = "POST";
					}
					con = RpcUtil.getRESTConnection(new URL(_url), method,
							new HashMap<String, String>() {
								{
									put("token", token);
								}
							});
					
					json = objmapper.writeValueAsString(em);
					System.out.println(json);
					RpcUtil.sendData(con, json.getBytes());
//					out.write(json.getBytes());
//					out.flush();
//					out.close();
					in = con.getInputStream();
					code = con.getResponseCode();
					in.close();
				}

			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return code >= 200;
	}

	@Override
	public PagingLoadResult<User> getUsers(Map<String, String> headers,
			PagingLoadConfig loadConfig) throws Exception {
		// TODO Auto-generated method stub
		return getDatas(headers, loadConfig, userses);
	}

	@Override
	public Class<?> getType() {
		// TODO Auto-generated method stub
		return User.class;
	}

	@Override
	public Response delete(Map<String, String> headers, final User selectedItem)
			throws Exception {
		Response response = new Response();
		InputStream in = null;
		HttpURLConnection con = null;
		try {
			String modUpdateUser = new StrSubstitutor(
					new HashMap<String, String>() {
						{
							put("id", Integer.toString(selectedItem.getId()));
						}
					}).replace(updateUser);
			con = RpcUtil.getRESTConnection(new URL(modUpdateUser), "DELETE",
					headers);
			in = con.getInputStream();
			int code = con.getResponseCode();
			response.setResponseCode(code);
			response.setSuccess(code == 200);
			if (code >= 500) {
				response.setJsonMetadata(IOUtils.toString(in));
			}
			return response;
		} catch (Exception e) {
			e.printStackTrace();
			response.setResponseCode(con.getResponseCode());
			response.setSuccess(false);
			response.setJsonMetadata(IOUtils.toString(in));
			return response;
		} finally {
			in.close();

		}
	}

	@Override
	public Response saveUser(final Map<String, String> headers, User user)
			throws Exception {
		InputStream in = null;
		Response response = new Response();
		try {
			String json = RpcUtil.objectToJson(user);
			HttpURLConnection con = RpcUtil.getRESTConnection(new URL(userses),
					"POST", headers);
			RpcUtil.sendData(con, json.getBytes());
			in = con.getInputStream();

			int code = con.getResponseCode();
			response.setResponseCode(code);
			response.setSuccess(code == 201);
			if (!response.isSuccess()) {
				throw new RuntimeException(IOUtils.toString(in));
			}

			return response;// CREATED RESPONSE CODE
		} catch (Exception e) {

			response.setJsonMetadata(e.getMessage());
			response.setSuccess(false);
			return response;
		} finally {
			if (in != null) {
				in.close();
			}

		}
	}

}
